<?php

require_once(dirname(__FILE__) . "/x_session_lib/x_session_store.php");
require_once(dirname(__FILE__) . "/x_session_lib/x_session.base.php");
require_once(dirname(__FILE__) . "/x_session_subdomain.conf.php");
require_once(dirname(__FILE__) . "/x_session.php");
require_once(dirname(__FILE__) . "/x_session.conf.php");

define("X_SESSION_RETURN_PARAM", "x_session_return");
define("X_SESSION_NAME_SUBDOMAIN", "X_SESSION_ID_SUBDOMAIN");

/**
 * Session class for the subdomain. If it does not find session cookie, it redirects user to the root domain
 * (then user automatically comes back). Session is started at the root domain (x_session class should be used 
 * for it). Cookie domain is .domain.ru (first symbol is '.') so it is accessible from all subdomains. If 
 * cookies are turned off, user receives error message. @todo
 * 
 * See examples for more info.
 * 
 * @todo rename subdomain -> smth. else (because it can be run from subfolders, not subdomains)
 */
class x_session_subdomain extends x_session_base
{

	protected $root_domain_redirect_url;

	/**
	 * @var x_session_conf_base
	 */
	protected $conf;

	/**
	 * @var x_session_store
	 */
	protected $store;

	/**
	 * @var x_session
	 */
	protected $x_session = null;

	protected $is_personal_session = false;

	protected $no_cookies_error = false;
	protected $no_cookies_error_original_url = "";
	protected $redirect_url = "";

	/**
	 * @param string $session_store_path - session storage path (i. e. /www/domain.ru/sessions 
	 * 		or ../../sessions (without the terminal slash)
	 * @param string $root_domain_redirect_url - URL to redirect to if the session cookie is not found.
	 * 		This is a URL at the root domain (i. e. http://domain.ru/set_cookie_and_redirect_back/
	 * 		if your code is run at http://subdomain.domain.ru/
	 * @param x_session_subdomain_conf $x_session_subdomain_conf - optional config
	 * @param x_session_conf $x_session_conf - optional config @todo
	 * @param boolean $write_begin - whether to keep the session opened for writing data. It is not 
	 * 		recommended to hold opened sessions for a long time, because of file locking and possible delay 
	 * 		in page load. Use instead session_write_begin(), session_write_commit() and 
	 * 		session_write_rollback() methods. If you keep the session opened, you should submit changes in
	 * 		$_SESSION using session_write_commit()
	 */
	public function __construct($session_store_path, $root_domain_redirect_url, x_session_subdomain_conf $x_session_subdomain_conf = null, x_session_conf $x_session_conf = null, $session_cookie_path = null, $session_cookie_domain = null, $write_begin = false)
	{
		parent::__construct($session_store_path);
		$this->root_domain_redirect_url = $root_domain_redirect_url;

		$this->conf = $x_session_subdomain_conf ? $x_session_subdomain_conf : new x_session_subdomain_conf();
		$is_authed = $this->try_auth_over_cookie($write_begin);

		if (!$is_authed)
		{
			$this->is_personal_session = true;
			$this->conf = $x_session_conf ? $x_session_conf : new x_session_conf();
			$this->conf->set_session_name(X_SESSION_NAME_SUBDOMAIN);
			$is_authed = $this->try_auth_over_cookie($write_begin);
			if (!$is_authed)
			{
				$this->create_new_session($session_cookie_path, $session_cookie_domain, $write_begin);
			}

			if (isset($_GET[X_SESSION_RETURN_PARAM]))
			{
				$this->no_cookies_error = true;
				$current_url = $this->get_current_url();
				$x_session_return_param_escaped = preg_quote(X_SESSION_RETURN_PARAM, "/");
				$this->no_cookies_error_original_url = preg_replace("/[?&]{$x_session_return_param_escaped}$/", "", $current_url);
			}
		}
		else
		{
			$conf = $x_session_conf ? $x_session_conf : new x_session_conf();
			$this->delete_personal_session_check($conf, $session_cookie_path, $session_cookie_domain);

			if (isset($_GET[X_SESSION_RETURN_PARAM]))
			{
				$current_url = $this->get_current_url();
				$x_session_return_param_escaped = preg_quote(X_SESSION_RETURN_PARAM, "/");
				$new_url = preg_replace("/([?&]){$x_session_return_param_escaped}$/", "", $current_url);
				if ($new_url != $current_url)
				{
					$this->redirect_url = $new_url;
				}
			}
		}
	}

	public function force_root_domain_session()
	{
		if ($this->is_personal_session())
		{
			if (!isset($_GET[X_SESSION_RETURN_PARAM]))
			{
				$this->set_redirect_url($this->root_domain_redirect_url);
			}
		}
	}

	public function is_personal_session()
	{
		return $this->is_personal_session;
	}

	public function get_no_cookies_error()
	{
		return $this->no_cookies_error;
	}

	public function get_no_cookies_error_original_url()
	{
		return $this->no_cookies_error_original_url;
	}

	public function get_redirect_url()
	{
		return $this->redirect_url;
	}

	protected function delete_personal_session_check(x_session_conf $conf, $session_cookie_path = null, $session_cookie_domain = null)
	{
		if (isset($_COOKIE[X_SESSION_NAME_SUBDOMAIN]))
		{
			$this->set_auth_cookie($conf, $session_cookie_path, $session_cookie_domain, 0, X_SESSION_NAME_SUBDOMAIN, '0', true);

			$session_id = $_COOKIE[X_SESSION_NAME_SUBDOMAIN];
			if (preg_match("/^[a-f0-9]{32}$/", $session_id))
			{
				$store = new x_session_store($this->session_store_path, $session_id, $conf->get_session_storage_deep_level());
				if ($store->session_exists())
				{
					$store->session_delete();
					$store->__destruct();
				}
			}
		}
	}

	protected function set_redirect_url($root_domain_redirect_url)
	{
		$current_url = $this->get_current_url();

		$return_url = $current_url;
		$return_url .= strpos($current_url, "?") ? "&" : "?";
		$return_url .= X_SESSION_RETURN_PARAM;

		$redirect_url = $root_domain_redirect_url;
		$redirect_url .= (strpos($root_domain_redirect_url, "?") ? "&" : "?");
		$redirect_url .= "return_url=" . rawurlencode($return_url);

		$this->redirect_url = $redirect_url;
	}

	protected function get_current_url()
	{
		$current_url = strpos($_SERVER["SERVER_PROTOCOL"], "HTTPS") === false ? "http" : "https";
		$current_url .= "://";
		$current_url .= $_SERVER["HTTP_HOST"];
		$current_url .= $_SERVER['REQUEST_URI'];
		return $current_url;
	}

}

?>